﻿#include "VulkanRectWidget.h"
#include "Render/VulkanContext.h"
#include "Render/Widget/VulkanWindow.h"

CVulkanRectWidgets::~CVulkanRectWidgets()
{
    //销毁command buffer
    CVulkanContext::Get()->GetRecycleObjects()->CommandBuffers.Add(CommandBuffer);
}

void CVulkanRectWidgets::PreProcess(const TVector<SPreRenderRectWidget> &AllRectData)
{
    TVector<SPreRenderRectWidget> ValidData;
    for (const auto& RectData : AllRectData)
    {
        //检查数据是否合法
        if(RectData.Color.A==0)
        {
            continue;
        }

        if(RectData.Viewport.width<=0 || RectData.Viewport.height<=0)
        {
            continue;
        }

        //检查裁剪是否合法
        if(RectData.Scissor.extent.width<=0 || RectData.Scissor.extent.height<=0)
        {
            continue;
        }

        //如果裁剪矩形完全在视口外面，则不需要绘制
        if(RectData.Scissor.offset.x+RectData.Scissor.extent.width<=RectData.Viewport.x ||
            RectData.Scissor.offset.x>=RectData.Viewport.x+RectData.Viewport.width ||
            RectData.Scissor.offset.y+RectData.Scissor.extent.height<=RectData.Viewport.y ||
            RectData.Scissor.offset.y>=RectData.Viewport.y+RectData.Viewport.height)
        {
            continue;
        }


        ValidData.Add(RectData);
    }


    //创建渲染对象
    RectWidgets.Resize(ValidData.Num());
    for (int i = 0; i < ValidData.Num(); ++i)
    {
        RectWidgets[i].BindData(ValidData[i]);
    }

}

void CVulkanRectWidgets::CreateSelfRecordTasks(CVulkanWindow *InRenderSurface, SRenderCommandBuffers &OutCmdBuffersToExecute)
{
    if(RectWidgets.Num()==0)
    {
        return;
    }

    //创建command buffer
    if(!CommandBuffer)
    {
        //allocate a command buffer for this widget
        vk::CommandBufferAllocateInfo CommandBufferAllocateInfo=vk::CommandBufferAllocateInfo()
            .setCommandPool(CVulkanContext::Get()->GetRenderThreadCommandPool())
            .setLevel(vk::CommandBufferLevel::eSecondary)
            .setCommandBufferCount(1);

        CommandBuffer = CVulkanContext::Get()->GetDevice().allocateCommandBuffers(CommandBufferAllocateInfo)[0];
    }


    OutCmdBuffersToExecute.RectWidgetRenderPassCommandBuffers.Add(CommandBuffer);

    vk::CommandBufferInheritanceInfo CommandBufferInheritanceInfo=vk::CommandBufferInheritanceInfo()
        .setRenderPass(CVulkanContext::Get()->GetWidgetRenderPass())
        .setFramebuffer(InRenderSurface->GetCurrentFrameBuffer())
        .setSubpass(0)
    ;

    vk::CommandBufferBeginInfo CommandBufferBeginInfo=vk::CommandBufferBeginInfo()
        .setFlags(vk::CommandBufferUsageFlagBits::eRenderPassContinue)
        .setPInheritanceInfo(&CommandBufferInheritanceInfo);

    CommandBuffer.begin(CommandBufferBeginInfo);
    
    CommandBuffer.bindPipeline(vk::PipelineBindPoint::eGraphics,CVulkanContext::Get()->GetRectWidgetPipeline()->Pipeline);
    for (auto& RectWidget : RectWidgets)
    {
        RectWidget.Draw(CommandBuffer);
    }

    CommandBuffer.end();



}

void CVulkanRectWidget::BindData(SPreRenderRectWidget Data)
{
    RectData=Data;
}

void CVulkanRectWidget::Draw(vk::CommandBuffer CommandBuffer)
{
    //推送常量
    CVulkanContext::SRectVertexPushConstant PushConstantValue;
    PushConstantValue.Color[0]=RectData.Color.R;
    PushConstantValue.Color[1]=RectData.Color.G;
    PushConstantValue.Color[2]=RectData.Color.B;
    PushConstantValue.Color[3]=RectData.Color.A;
    PushConstantValue.ZOrder=RectData.Depth;

                    
    CommandBuffer.pushConstants(CVulkanContext::Get()->GetRectWidgetPipeline()->PipelineLayout                        
        ,vk::ShaderStageFlagBits::eVertex
        ,0
        ,PushConstantValue.GetSizeWithoutPadding()
        ,&PushConstantValue);


    CommandBuffer.setViewport(0,1,&RectData.Viewport);
    CommandBuffer.setScissor(0,1,&RectData.Scissor);
                       

    CommandBuffer.draw(4,1,0,0);
                    
}
